package main.java.com.negromotad.genetics.rules;

import java.util.ArrayList;
import java.util.List;

import org.jgap.Genotype;
import org.jgap.IChromosome;
import org.jgap.NaturalSelector;
import org.jgap.Population;

public class TMTargetSelector extends NaturalSelector {

	private int target;
	private Double[][] entry;
	private int rows;
	private int cols;
	private int expectative;

	public TMTargetSelector(Double[][] theEntry, int theRows, int theCols,
			int theTarget, int theExpectative) {
		target = theTarget;
		entry = theEntry;
		rows = theRows;
		cols = theCols;
		expectative = theExpectative;
	}

	@Override
	protected void add(IChromosome toAdd) {
	}

	@Override
	public void empty() {
	}

	@Override
	public boolean returnsUniqueChromosomes() {
		return false;
	}

	@Override
	public void select(int manyToSelect, Population from_population,
			Population to_population) {
		List<IChromosome> chromosomes = from_population.getChromosomes();
		List<IChromosome> spareChromosomes = new ArrayList<IChromosome>();
		for (IChromosome chrome : chromosomes) {
			Double totalRisk = caculateRisk(chrome);
			if (totalRisk < target) {
				to_population.addChromosome((IChromosome) chrome.clone());
				// System.out.println("Total is: "+totalRisk+" and expectative is: "+expectative+". Risk: "+totalRisk);
			} else {
				spareChromosomes.add(chrome);
			}
		}
		if (to_population.getChromosomes().size() == 0) {
			System.out
					.println("The total of the population has been discarded.");
			to_population.setChromosomes(spareChromosomes);
		}
	}

	private Double caculateRisk(IChromosome chrome) {
		Double totalRisk = 0.0;
		Double totalColumn;
		for (int i = 0; i < rows; i++) {
			totalColumn = 0.0;
			for (int j = 0; j < cols; j++) {
				totalColumn += ((Integer) chrome.getGene(j).getAllele())
						* entry[i][j] / 100;
			}
			if (totalColumn < expectative) {
				totalRisk += expectative - totalColumn;
			}
			if (totalRisk > target) {
				return totalRisk;
			}
		}
		return totalRisk;
	}

}
